/*
 * queue.c
 *
 *  Created on: 2015-5-15
 *      Author: likui
 */

#include "queue.h"
#include "error.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

/**
 * @brief  初始化队列结构元素
 * @param queue 指向队列结构的指针
 * @param queue_size 需要创建的队列长度
 * @return 若创建成功则为true，若失败则为false
 */
bool queue_init(queue_t *queue, int queue_size)
{
	queue->elems_len = queue_size + 1;		// 队列长度（因为队列满时，有一个位置为空，所以需要加1）

	// 动态分配队列元素空间
	queue->elems = (ELEMTYPE *)malloc(queue_size * sizeof(ELEMTYPE));
	if (queue->elems == NULL) {
		fprintf(stderr, "malloc error: %s\n", strerror(errno));
		return false;
	}

	queue->front = 0;						// 头指针
	queue->rear = 0;						// 尾指针

	return true;
}

/**
 * @brief 销毁队列
 * @param queue 指向队列结构的指针
 */
void queue_destroy(queue_t *queue)
{
	queue->front = 0;						// 头指针
	queue->rear = 0;						// 尾指针

	free(queue->elems);					// 释放队列元素空间
	queue->elems = NULL;					// 将指针置为空
	queue->elems_len = 0;					// 队列长度
}

/**
 * @brief 添加新元素到队列尾部
 * @param queue 指向队列结构的指针
 * @param elem 待添加的元素
 * @return 若成功则为true，若失败则为false
 */
bool queue_add(queue_t *queue, ELEMTYPE elem)
{
#ifndef NDEBUG
	error_msg("queue add:");
#endif
	if (queue_is_full(queue)) {
		return false;
	}

	queue->elems[queue->rear] = elem;						// 先放入值，再增加指针（指针只向的值为空）
	queue->rear = (queue->rear + 1) % queue->elems_len;	// 尾指针指向的位置为空

	return true;
}

/**
 * @brief 从队列首部删除元素
 * @param queue 指向队列结构的指针
 * @return 若成功为被删除的元素值，若失败则为NULL
 */
ELEMTYPE queue_del(queue_t *queue)
{
	int index;

	if (queue_is_empty(queue)) {
		return NULL;
	}

	index = queue->front;										// 头指针指向的值不为空
	queue->front = (queue->front + 1) % queue->elems_len;	// 头指针

	return queue->elems[index];								// 返回元素值
}

/**
 * @brief 判断队列是否为空
 * @param queue 指向队列结构的指针
 * @return 若队列为空返回true，若队列非空则返回false
 */
bool queue_is_empty(queue_t *queue)
{
	if (queue->front == queue->rear) {
		return true;
	}
	return false;
}

/**
 * @brief 判断队列是否为满
 * @param queue 指向队列结构的指针
 * @return 若队列为满返回true，若队列非满则返回false
 */
bool queue_is_full(queue_t *queue)
{
	if ( ((queue->rear + 1) % queue->elems_len) == queue->front) {
		return true;
	}

	return false;
}

/**
 * @brief 输出队列中的值
 * @param queue 指向队列结构的指针
 */
void queue_print(queue_t *queue)
{
	int index;

	index = queue->front;

	while (index != queue->rear) {
		printf("index = %d, data = %lx\n", index, (uint64_t)queue->elems[index]);
		index  = (index + 1) % queue->elems_len;
	}
}
